home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
wil4c10.zip
/
BCAST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-26
|
14KB
|
575 lines
/*
** BCAST.C (email broadcast)
**
** SMTP client, uses ASYNC functions.
**
** Note that this program reads BCAST.INI, which contains the
** following 4 text lines:
**
** SMTP=your_SMTP_server_address
** FROM=your_email_address
** RCPT=file_with_list_of_email_addresses
** MAIL=file_to_email
**
** This program emails the file specified by the "MAIL=" entry
** to each email address in the file specified by the "RCPT=" entry.
**
** A typical application would be to mail out a newsletter to a list
** of subscribers.
*/
#include <windows.h>
#include <winsock.h>
#include "wil.h"
#include "about.h"
#include "async.h"
#include "message.h"
#include "paint.h"
#include "readini.h"
#include "str.h"
#ifdef WIN32
#define USE_INS HINSTANCE
#define USE_PTR PSTR
#else
#define USE_INS HANDLE
#define USE_PTR LPSTR
#endif
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
/* globals */
HWND hMainWnd; /* main window handle */
#define BS 8
#define LF 10
#define CR 13
#define ESC 27
#define MAX_BUF 512
#define STR_SIZE 50
#define SMTP_PORT 25
#define SMTP_BEGIN 601
#define SMTP_CONN_SUCCESS 602
#define SMTP_HELO_SUCCESS 603
#define SMTP_FROM_SUCCESS 604
#define SMTP_TO_SUCCESS 605
#define SMTP_DATA_SUCCESS 606
#define SMTP_SEND 607
#define SMTP_QUIT_BEGIN 701
#define SMTP_QUIT_SUCCESS 702
#define SMTP_QUIT_FAILURE 703
static USE_INS hInstance;
static int WinWidth = 8 * NCOLS; /* window width */
static int WinHeight = 15 * NROWS;/* window height */
static char Temp[MAX_BUF+8]; /* temprary buffer */
static char InBuffer[MAX_BUF+1]; /* input buffer */
static SOCKET Socket = 0; /* socket */
static int EchoFlag = 1; /* echo commands of TRUE */
static HCURSOR ArrowCursor; /* arrow cursor */
static HCURSOR WaitCursor; /* hour glass cursor */
static char SmtpString[STR_SIZE] = ""; /* SMTP server */
static char FromString[STR_SIZE] = ""; /* our email address */
static char RcptFile[STR_SIZE] = ""; /* destination list (user@adress) */
static char MailFile[STR_SIZE] = ""; /* name of file to broadcast */
/* display error message */
static void DisplayError(int Code, LPSTR Msg)
{wsprintf((LPSTR)Temp,"ERROR %d: ",Code);
DisplayString((LPSTR)Temp);
if(Msg) DisplayString(Msg);
if(Code)
{wilErrorText(Code,(LPSTR)Temp,50);
DisplayLine((LPSTR)Temp);
}
/* restore arrow cursor */
SetCursor(ArrowCursor);
}
/* read text line (ending with LF) from disk */
static int ReadTextLine(int Handle, LPSTR Buffer, int BufLen)
{char Ch;
int i;
int Size = 0;
static char TextBuffer[128];
static int TextLeft = 0;
static int TextRight = 0;
while(1)
{/* is TextBuffer[] empty ? */
if(TextLeft>=TextRight)
{/* read from disk */
TextLeft = 0;
TextRight = _lread(Handle,(LPSTR)TextBuffer,125) - 1;
if(TextRight<0) return -1;
}
/* copy till LF or end of buffer */
for(i=TextLeft;i<=TextRight;i++)
{Ch = TextBuffer[i];
Buffer[Size++] = 0x7f & Ch;
if(Ch=='\n')
{/* found LF */
Buffer[Size] = '\0';
TextLeft = i + 1;
return Size;
}
/* is Buffer[] filled ? */
if(Size==BufLen-3)
{/* end with CR/LF */
Buffer[Size++] = '\r';
Buffer[Size++] = '\n';
Buffer[Size] = '\0';
TextLeft = i + 1;
return Size;
}
}
/* used up all of TextBuffer[] */
TextLeft = TextRight;
} /* end-while */
}
/* WinMain */
#ifdef WIN32
int WINAPI
#else
int PASCAL
#endif
WinMain(USE_INS hInst, USE_INS hPrevInstance,
USE_PTR szCmdLine, int nCmdShow)
{WNDCLASS wc;
MSG msg;
BOOL Result;
if(!hPrevInstance)
{/* register main window class */
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, "HostIcon");
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "HostMenu";
wc.lpszClassName = "HostWClass";
Result = RegisterClass(&wc);
if(!Result) return FALSE;
}
/* create main window */
hInstance = hInst;
hMainWnd = CreateWindow(
"HostWClass", "BCAST", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
WinWidth, WinHeight,
NULL, NULL,
hInstance, NULL);
ShowWindow(hMainWnd, nCmdShow);
UpdateWindow(hMainWnd);
/* window control loop */
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
} /* end WinMain */
#ifdef WIN32
LRESULT CALLBACK
#else
long FAR PASCAL
#endif
MainWndProc(HWND hWindow,UINT iMsg,WPARAM wParam,LPARAM lParam)
{int Code;
HDC hDC;
PAINTSTRUCT ps;
LPSTR Ptr;
static int BufSize;
static int RcptHandle = 0;
static int MailHandle = 0;
#ifdef WIN32
#else
static FARPROC lpfnAboutDlgProc;
#endif
/* begin */
hMainWnd = hWindow;
switch (iMsg)
{case WM_CREATE:
/* create cursors */
ArrowCursor = LoadCursor(NULL, IDC_ARROW);
WaitCursor = LoadCursor(NULL, IDC_WAIT);
SetCursor(ArrowCursor);
#ifdef WIN32
#else
/* create thunk for Win16 */
lpfnAboutDlgProc = MakeProcInstance(AboutDlgProc,hInstance);
#endif
/* initialize paint module */
PaintInit();
/* attach WINSOCK */
DisplayString("Attaching WINSOCK...");
Code = wilAttach();
DisplayLine("OK");
if(Code<0) DisplayError(Code,"wilAttach fails:");
else
{wsprintf((LPSTR)Temp," Description: %s", wilGetDescription() );
DisplayLine((LPSTR)Temp);
wsprintf((LPSTR)Temp," My HostName: %s", wilGetMyHostName() );
DisplayLine((LPSTR)Temp);
wsprintf((LPSTR)Temp," My HostAddr: %s", wilGetMyHostDotted(0) );
DisplayLine((LPSTR)Temp);
}
/* open BCAST.INI file */
if(!IniOpen("BCAST.INI")) break;
while(1)
{/* read next line from BCAST.INI */
if(IniRead((LPSTR)Temp)<0) break;
#if 0
/* echo strings */
DisplayLine((LPSTR)Temp);
#endif
/* test for all legal keywords */
IniExtract((LPSTR)Temp,"SMTP",(LPSTR)SmtpString);
IniExtract((LPSTR)Temp,"FROM",(LPSTR)FromString);
IniExtract((LPSTR)Temp,"RCPT",(LPSTR)RcptFile);
IniExtract((LPSTR)Temp,"MAIL",(LPSTR)MailFile);
}
/* verify that we have all strings read in */
if(lstrlen((LPSTR)SmtpString)==0) DisplayLine("ERROR: Missing SMTP string.");
else
{wsprintf((LPSTR)Temp,"SMTP server is '%s'", (LPSTR)SmtpString);
DisplayLine((LPSTR)Temp);
}
if(lstrlen((LPSTR)FromString)==0) DisplayLine("ERROR: Missing FROM string.");
else
{wsprintf((LPSTR)Temp,"FROM address is '%s'", (LPSTR)FromString);
DisplayLine((LPSTR)Temp);
}
if(lstrlen((LPSTR)RcptFile)==0) DisplayLine("ERROR: Missing RCPT filename.");
else
{wsprintf((LPSTR)Temp,"RCPT file is '%s'", (LPSTR)RcptFile);
DisplayLine((LPSTR)Temp);
}
if(lstrlen((LPSTR)MailFile)==0) DisplayLine("ERROR: Missing MAIL filename.");
else
{wsprintf((LPSTR)Temp,"SMTP server is '%s'", (LPSTR)MailFile);
DisplayLine((LPSTR)Temp);
}
/* open file to send */
MailHandle = _lopen((LPSTR)MailFile,OF_READ|OF_SHARE_DENY_WRITE);
if(MailHandle<0)
{DisplayString("ERROR: Cannot open ");
DisplayLine((LPSTR)MailFile);
break;
}
/* open RCPT file */
RcptHandle = _lopen((LPSTR)RcptFile,OF_READ|OF_SHARE_DENY_WRITE);
if(RcptHandle<0)
{DisplayString("ERROR: Cannot open ");
DisplayLine((LPSTR)RcptFile);
break;
}
break;
case WM_COMMAND:
switch(wParam)
{
case MSG_ABOUT :
#ifdef WIN32
DialogBox(hInstance, "AboutBox", hMainWnd, AboutDlgProc);
#else
DialogBox(hInstance, "AboutBox", hMainWnd, lpfnAboutDlgProc);
#endif
return 0;
case MSG_BREAK:
wilCancelBlocking();
wilCloseSocket(Socket);
break;
case MSG_EXIT:
wilRelease();
DestroyWindow(hMainWnd);
break;
case MSG_MAIL_PUT:
/* lets go do the email */
POST_MSG(SMTP_BEGIN);
break;
}
break;
case WM_USER: /* posted by WIL */
AsyncProcessMsg(lParam);
break;
case WM_USER+1: /* posted by POST_MSG [defined in async.h] */
/* test response code */
if(lParam>=500)
{/* SMTP server returns fatal error code */
POST_MSG(SMTP_QUIT_FAILURE);
break;
}
/* execute case */
switch(wParam)
{
case SMTP_BEGIN:
AsyncSetEcho(TRUE);
SetCursor(WaitCursor);
/* connect to SMTP server */
Socket = AsyncConnect(hMainWnd,"SMTP",(LPSTR)SmtpString,
SMTP_PORT, SMTP_CONN_SUCCESS,
SMTP_QUIT_FAILURE, ASYNC_SINGLE_LINE);
break;
case SMTP_CONN_SUCCESS:
/* send HELO (hello) command */
Ptr = StringChar((LPSTR)FromString,'@');
wsprintf((LPSTR)Temp,"HELO %s",(LPSTR)(Ptr+1));
AsyncCommand((LPSTR)Temp, SMTP_HELO_SUCCESS,
SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
break;
case SMTP_HELO_SUCCESS:
/* send MAIL FROM command */
wsprintf((LPSTR)Temp,"MAIL FROM:<%s>",(LPSTR)FromString);
AsyncCommand((LPSTR)Temp,SMTP_FROM_SUCCESS,
SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
break;
case SMTP_FROM_SUCCESS:
/* read next email destination address */
BufSize = ReadTextLine(RcptHandle, (LPSTR)InBuffer, MAX_BUF);
if(BufSize<=0)
{/* end of RCPT file */
_lclose(RcptHandle);
POST_MSG(SMTP_TO_SUCCESS);
}
/* strip trailing CR, LF from RCPT string */
StripCRLF((LPSTR)InBuffer);
/* do (minimal) email address validation */
Ptr = StringChar((LPSTR)Temp,'@');
if(Ptr==NULL)
{wsprintf((LPSTR)Temp,"Email address '%s' missing '@' (skipping)");
DisplayString((LPSTR)Temp);
POST_MSG(SMTP_FROM_SUCCESS);
}
/* send RCPT TO (receipt to) command */
wsprintf((LPSTR)Temp,"RCPT TO:<%s>",(LPSTR)InBuffer);
AsyncCommand((LPSTR)Temp, SMTP_FROM_SUCCESS,
SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
break;
case SMTP_TO_SUCCESS:
/* send DATA command */
AsyncCommand("DATA", SMTP_DATA_SUCCESS,
SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
break;
case SMTP_DATA_SUCCESS:
/* get next line from disk */
BufSize = ReadTextLine(MailHandle, (LPSTR)InBuffer, MAX_BUF);
if(BufSize<=0)
{/* end of file */
_lclose(MailHandle);
/* append line with only '.' */
wilWriteString(Socket,".\r\n");
DisplayLine("<EOF>");
POST_MSG(SMTP_QUIT_BEGIN);
break;
}
/* ready to send text line */
POST_MSG(SMTP_SEND);
break;
case SMTP_SEND:
/* does buffer consist of lone '.' ? */
if((InBuffer[0]=='.')&&(InBuffer[1]=='\r')&&(InBuffer[2]=='\n'))
{/* "quote" the period */
InBuffer[1] = '.';
InBuffer[2] = '\r';
InBuffer[3] = '\n';
InBuffer[4] = '\0';
BufSize = 4;
}
/* send the buffer */
Code = wilWriteSocket(Socket,(LPSTR)InBuffer,BufSize);
if(Code<0)
{/* socket write error */
DisplayError(Code, "WriteSocket:");
POST_MSG(SMTP_QUIT_FAILURE);
break;
}
if(EchoFlag) WriteTheString((LPSTR)InBuffer,BufSize);
/* go get another buffer to write */
BufSize = 0;
POST_MSG(SMTP_DATA_SUCCESS);
break;
case SMTP_QUIT_BEGIN:
AsyncSetEcho(TRUE);
/* send QUIT command */
AsyncCommand("QUIT", SMTP_QUIT_SUCCESS,
SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
break;
case SMTP_QUIT_FAILURE:
DisplayLine("SMTP command has failed...");
wilCloseSocket(Socket);
SetCursor(ArrowCursor);
break;
/* fall thru... */
case SMTP_QUIT_SUCCESS:
/* all done */
DisplayLine("SMTP command succeeds.");
wilCloseSocket(Socket);
SetCursor(ArrowCursor);
break;
} /* end-switch(wParam) */
case WM_PAINT:
HideCaret(hMainWnd);
hDC = BeginPaint(hMainWnd, &ps);
SetMapMode(hDC,MM_ANISOTROPIC);
SelectObject(hDC, GetStockObject(OEM_FIXED_FONT) );
PaintMain(hDC,&ps);
EndPaint(hMainWnd,&ps);
SetCaretPos(PaintGetColPos(),PaintGetRowPos());
ShowCaret(hMainWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hMainWnd, iMsg, wParam, lParam));
}
return 0;
} /* end MainWndProc */